package nice_ticks;

require Exporter;


our @ISA = qw(Exporter);

our $VERSION = 1.00;
our @EXPORT = qw(nice_ticks nicenum get_ticks_format_str);
use strict;
use warnings;
use Carp;
use Data::Dump qw(dump);
use POSIX qw(log10 ceil floor);

sub expt($$)
{
	my ($a,  $n) = @_;
	my $x = 1.0;
	if ($n > 0)
	{
		$x *= $a for(1..$n);
	}
	elsif ($n < 0)
	{
		$x /= $a for(1..-$n);
	}
	return $x;
}


sub get_ticks_format_str($)
{
	my ($d) = @_;
	my $nfrac =int(-floor(log10($d)));	# # of fractional digits to show */
	$nfrac = 0 if $nfrac < 0;
	return sprintf("%%.%df", $nfrac);	# simplest axis labels */

}
#/*
# * loose_label: demonstrate loose labeling of data range from min to max.
# * (tight method is similar)
# */

sub nice_ticks($$$$)
{
	my ($mini, $maxi, $max_cnt_ticks, $cnt_minor_ticks) = @_;
	
    # we expect $mini!=$maxi
    my $range = nicenum($maxi-$mini, 0);
	
	
	
	# tick mark spacing */
    my $d = nicenum($range/($max_cnt_ticks-1), 1);

	# graph range $mini and $maxi */
    my $graphmin = floor($mini/$d)*$d;
    my $graphmax = ceil($maxi/$d)*$d;

	# me
	$d = nicenum(($graphmax - $graphmin)/($max_cnt_ticks), 0);
	$graphmin = floor($mini/$d)*$d;
	$graphmax = ceil($maxi/$d)*$d; 

	# me
	my $minor_d = nicenum($d / $cnt_minor_ticks, 0);
	
    my $str = get_ticks_format_str($d);

	return ($graphmin, $graphmax, $d, $str, $minor_d);
    #for (my $x=$graphmin; $x<$graphmax+.5*$d; $x+=$d) 
	#{
	#	my $temp = sprintf($str, $x);
	#	printf("(%s)\n", $temp);
    #}
}

#/*
# * nicenum: find a "nice" number approximately equal to x.
# * Round the number if round=1, take ceiling if round=0
# */

sub nicenum($$)
{
	my ($x, $round) = @_;

	#/* exponent of $x */
    my $expv = floor(log10($x));

	#/* fractional part of $x */
	# /* between 1 and 10 */
    my $f = $x / expt(10., $expv);		

	#/* nice, rounded fraction */
	my $nf;
	
    if ($round)
	{
		if ($f<1.5)
		{
			$nf = 1.;
		}
		elsif ($f<3.)
		{
			$nf = 2.;
		}
		elsif ($f<7.)
		{
			$nf = 5.;
		}
		else
		{
			$nf = 10.;
		}
	}
    else
	{
		if ($f<=1.)
		{
			$nf = 1.;
		}
		elsif ($f<=2.)
		{
			$nf = 2.;
		}
		elsif ($f<=5.)
		{
			$nf = 5.;
		}
		else
		{
			$nf = 10.;
		}
	}
    return $nf*expt(10., $expv);
}


#my ($graphmin, $graphmax, $d, $str, $minor_d) = nice_ticks(0.5, 4, 8);
#print STDERR $minor_d, "\n";
#for (my $x=$graphmin; $x<$graphmax+.5*$d; $x+=$d) 
#{
#	my $temp = sprintf($str, $x);
#	printf("(%s)\n", $temp);
#}
1;
